import javax.swing.*;
import java.io.*;
public class MyDatabase implements Database{
	Node head; Node tail; Node listI;
	int elements = 0;
	public int getElements(){
		Node l;
		int cnt = 1;
		l = head;
		while(l.next!=null){
			l = l.next;
			cnt++;
		}
		return cnt;
	}
	public Node getTail(){
		Node l; l = head;
		while(l.next!=null){
			l = l.next;
		}
		return l;
	}
	public void stack(Node myNode){
		if (head == null) {
			head = myNode;
			tail = myNode;
		} else {
			Node temp;
			temp = head;
			myNode.next= head;
			head = myNode;
			temp.previous = head;	
		}
		elements = elements + 1;
	}
	public void queue(Node myNode){
		if(head==null){	
		head = myNode;
		tail = head;
			}
		else{
		Node temp;
		temp = tail;
		tail.next = myNode;
		tail = myNode;
		tail.previous = temp;
			}
		elements = elements + 1;
	}
	public void SpecCase(Node myNode){
		head = myNode;
		head.next = tail;
		tail.previous = head;
		elements++;
	}
	public void rove(Node myNode){
		int i = 0; int j = 0; int m = 0;
		Node l = head;
		while(i<=elements - 1){
			boolean k = myNode.equals(l);
			if(k==true){
				i = elements + 1; m = 1;
			}
			else if(k==false){
				l = l.next;
				i++;
			}
		}
		if(m==0){
			l = head;
			int n = 0;
			while(n==0){
				double c1, c2, c3; c1 = myNode.cI; c2 = l.cI; c3 = l.next.cI;
				if(c1<=c2&&c1>c3){
					myNode.next = l.next;
					myNode.previous = l;
					l.next = myNode;
					myNode.next.previous = myNode;
					n++;
					elements = elements + 1;
				}
				else if(c1<c2&&c1==c3){
					myNode.next = l.next;
					myNode.previous = l;
					l.next = myNode;
					myNode.next.previous = myNode;
					n++;
					elements = elements + 1;
				}
				else if(c1==c2&&c1==c3){
					myNode.next = l.next;
					myNode.previous = l;
					l.next = myNode;
					myNode.next.previous = myNode;
					n++;
					elements = elements + 1;
				}
				else{
					l = l.next;
				}
			}
		}
	}
	public void SDel(){
		if(head.next!=null){
			head = head.next; elements = elements - 1;
		}else{
			head = null; elements = 0;
		}
	}
	public void EDel(){
		int p = 1; Node l; l = head;
		tail = tail.previous; tail.next = null;
		elements = elements - 1;
	}
	public void RDel(Node nodeToDelete){
		Node l;
		l = head;
		int q; q = 0;
		while(q==0){
			if(l.next!=null){
				if(!nodeToDelete.equals(l.next)){
					l = l.next;
				}
				else{
					Node temp; temp = l.next.next;
					l.next = null; l.next = temp;
					l.next.previous = l;
					elements = elements - 1;
					q++;
				}
			}
			else{
				JOptionPane.showMessageDialog(null, "No node like that!", "Chan DB", JOptionPane.INFORMATION_MESSAGE);
				q++;
			}
		}
	}
	public Node CS(Node nodeToSearch){
		int q = 0; Node l; l = head; int w = 0; Node z = new Node();
		while(q==0){
			if(l.next!=null){
				if(!nodeToSearch.equals(l)){
					l = l.next;
				}
				else{
					q++;
					z = l;
					w = 1;
				}
			}
			else{
				q++;
				w = 0;
				;
			}
		}
		if(w==1){
			return z;
		}else{
			return null;
		}
	}
	public void insert(Node myNode){
		if(head==null){
			queue(myNode);
		}
		else{
			double c1, hc, tc;
			hc = head.cI;
			tc = tail.cI;
			c1 = myNode.cI;
			boolean g = myNode.equals(head);
			boolean h = myNode.equals(tail);
			if(g==false&&h==false){
				if(c1>=hc&&elements>1){
					stack(myNode);
				}
				else if(c1>=hc&&elements==1){
					SpecCase(myNode);
				}
				else if(c1<tc){
					queue(myNode);
				}
				else if(c1==tc&&elements>1){
					queue(myNode);
				}
				else if(c1<hc&&c1>tc){
					rove(myNode);
				}
			}
		}
	}
	public boolean delete(Node nodeToDelete){
		if(listI.equals(nodeToDelete)){
			Node c = listback();
		}
		if(nodeToDelete.equals(head)){
			SDel();
		}
		else if(nodeToDelete.equals(tail)){
			EDel();
		}
		else if(!nodeToDelete.equals(head)&&!nodeToDelete.equals(tail)){
			RDel(nodeToDelete);
		}
		return true;
	}
	public boolean replace(Node nodeToReplace, Node myNode){
		boolean c; c = delete(myNode);
		if(c==true){
			insert(nodeToReplace);
		}
		return true;
	}
	public Node search(Node nodeToSearch){
		boolean d, e;
		d = nodeToSearch.equals(head);
		e = nodeToSearch.equals(tail);
		if(d==true){
			return head;
		}
		else if(e==true){
			return tail;
		}
		else{
			Node f; f = CS(nodeToSearch);
			return f;
		}
	}
	public Node listIterator(){
		if(listI==null){
			listI = head;
			return head;
		}
		/*else if(listI==tail&&elements>1){
			listI = null;
			return null;
		}*/
		else if(listI==tail){
			listI = head;
			return head;
		}
		else{
			listI = listI.next;
			return listI;
		}
	}
	public Node listback(){
		if(listI==null){
			listI = tail;
			return tail;
		}
		/*else if(listI==tail&&elements>1){
			listI = null;
			return null;
		}*/
		else if(listI==head){
			listI = tail;
			return tail;
		}
		else{
			listI = listI.previous;
			return listI;
		}
	}
	public String whoIAm(){
		return "I am Christian Edensor V. Arbon a.k.a. Chan!\nA good chess player has at least 16 strategies for the game and\nat least 16 real time tactic per move";
	}
	public boolean equals(MyDatabase o){
		if(o.elements==elements){
			if(head.equals(o.head)){
				return true;
			}
			else{
				return false;
			}
		}
		else{
			return false;
		}
	}
	public boolean saveToFile(File file) throws Exception{
		//File myFile = new File(file);
		FileOutputStream x = new FileOutputStream(file);
		ObjectOutputStream xO = new ObjectOutputStream(x);
		xO.writeObject(head);
		xO.close();
		return true;
	}
	public boolean loadFromFile(File file) throws Exception{
		//File myFile = new File(file);
		FileInputStream y = new FileInputStream(file);
		ObjectInputStream yO = new ObjectInputStream(y);
		try{
			Object temp = yO.readObject();
			if(temp.getClass().getName().equals("Node")){
				head = (Node) temp;
				elements = getElements();
				tail = getTail();
			}
		}catch(EOFException e){
			System.out.println("File loaded!");
		}
		yO.close();
		return true;
	}

}